import { useClipboard } from '@vueuse/core'
import * as Diff from 'diff'
import { ElMessage } from 'element-plus'

// 差异统计类型
export interface DiffStats {
  added: number
  removed: number
  total: number
}

// 折叠配置类型
export interface FoldingConfig {
  enabled: boolean
  threshold: number
  expandedSections: Set<string>
}

// HTML转义函数
export function escapeHtml(text: string): string {
  return text
    .replace(/&/g, '&amp;')
    .replace(/</g, '&lt;')
    .replace(/>/g, '&gt;')
}

// 计算差异
export function compareDiff(
  leftText: string,
  rightText: string,
  diffMode: 'chars' | 'words' | 'lines',
  foldingConfig: FoldingConfig,
  diffStats: DiffStats,
): string[] {
  if (!leftText.trim() || !rightText.trim()) {
    ElMessage.warning('请在左右两侧都输入需要对比的文本')
    return []
  }

  let changes: Diff.Change[]

  switch (diffMode) {
    case 'chars':
      changes = Diff.diffChars(leftText, rightText)
      break
    case 'words':
      changes = Diff.diffWords(leftText, rightText)
      break
    case 'lines':
    default:
      changes = Diff.diffLines(leftText, rightText)
      break
  }

  // 重置统计信息
  diffStats.added = 0
  diffStats.removed = 0
  diffStats.total = 0

  // 计算差异统计
  if (diffMode === 'lines') {
    changes.forEach((part) => {
      if (part.added) {
        const lines = part.value.split('\n').length - (part.value.endsWith('\n') ? 1 : 0)
        diffStats.added += lines
        diffStats.total += lines
      }
      else if (part.removed) {
        const lines = part.value.split('\n').length - (part.value.endsWith('\n') ? 1 : 0)
        diffStats.removed += lines
        diffStats.total += lines
      }
    })
  }
  else {
    changes.forEach((part) => {
      if (part.added) {
        diffStats.added += part.value.length
        diffStats.total += part.value.length
      }
      else if (part.removed) {
        diffStats.removed += part.value.length
        diffStats.total += part.value.length
      }
    })
  }

  const result: string[] = []
  let lineNumber = 1

  // 处理折叠逻辑
  if (foldingConfig.enabled && diffMode === 'lines') {
    let sectionId = 0

    changes.forEach((part) => {
      if (!part.added && !part.removed) {
        const lines = part.value.split('\n')

        if (lines.length > foldingConfig.threshold) {
          const prefix = lines.slice(0, 2)
          const suffix = lines.slice(-2)
          const foldedLines = lines.length - 4
          const currentSectionId = `fold-${sectionId++}`

          result.push('<div class="diff-block diff-equal-block">')
          prefix.forEach((line, i) => {
            if (i === prefix.length - 1 && line === '') {
              return
            }
            result.push(`
              <div class="diff-line">
                <span class="line-number">
                 ${lineNumber++}
                </span>
                <span class="diff-equal">${escapeHtml(line)}</span>
              </div>
            `)
          })
          result.push('</div>')

          result.push(`
            <div class="folded-section">
              <button class="fold-toggle" data-section-id="${currentSectionId}" onclick="window.toggleFold('${currentSectionId}')">
                <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="fold-icon"><polyline points="6 9 12 15 18 9"></polyline></svg>
                ${foldedLines} 行相同内容已折叠
              </button>
              <div id="${currentSectionId}" class="folded-content" style="display: none;">
                <div class="diff-block diff-equal-block">
                  ${lines.slice(2, -2).map((line) => {
                    if (line === '') {
                      return ''
                    }
                    return `
                      <div class="diff-line">
                        <span class="line-number">${lineNumber++}</span>
                        <span class="diff-equal">${escapeHtml(line)}</span>
                      </div>
                    `
                  }).join('')}
                </div>
              </div>
            </div>
          `)

          result.push('<div class="diff-block diff-equal-block">')
          suffix.forEach((line, i) => {
            if (i === suffix.length - 1 && line === '') {
              return
            }
            result.push(`
              <div class="diff-line">
                <span class="line-number">${lineNumber++}</span>
                <span class="diff-equal">${escapeHtml(line)}</span>
              </div>
            `)
          })
          result.push('</div>')
        }
        else {
          result.push('<div class="diff-block diff-equal-block">')
          lines.forEach((line, i) => {
            if (i === lines.length - 1 && line === '') {
              return
            }
            result.push(`
              <div class="diff-line">
                <span class="line-number">${lineNumber++}</span>
                <span class="diff-equal">${escapeHtml(line)}</span>
              </div>
            `)
          })
          result.push('</div>')
        }
      }
      else {
        const className = part.added ? 'diff-added' : 'diff-removed'
        const blockClass = part.added ? 'diff-added-block' : 'diff-removed-block'
        const icon = part.added
          ? '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="diff-icon"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>'
          : '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="diff-icon"><line x1="5" y1="12" x2="19" y2="12"></line></svg>'

        const lines = part.value.split('\n')

        result.push(`<div class="diff-block ${blockClass}">`)
        lines.forEach((line, i) => {
          if (i === lines.length - 1 && line === '') {
            return
          }
          result.push(`
            <div class="diff-line">
              <span class="line-number">${part.added ? '+' : '-'}</span>
              <span class="diff-marker">${icon}</span>
              <span class="${className}">${escapeHtml(line)}</span>
            </div>
          `)
        })
        result.push('</div>')
      }
    })
  }
  else {
    if (diffMode === 'lines') {
      changes.forEach((part) => {
        const className = part.added
          ? 'diff-added'
          : part.removed
            ? 'diff-removed'
            : 'diff-equal'
        const blockClass = part.added
          ? 'diff-added-block'
          : part.removed
            ? 'diff-removed-block'
            : 'diff-equal-block'

        const lines = part.value.split('\n')

        result.push(`<div class="diff-block ${blockClass}">`)
        lines.forEach((line, i) => {
          if (i === lines.length - 1 && line === '') {
            return
          }

          let linePrefix: string | number = lineNumber++
          let icon = ''

          if (part.added || part.removed) {
            linePrefix = part.added ? '+' : '-'
            icon = part.added
              ? '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="diff-icon"><line x1="12" y1="5" x2="12" y2="19"></line><line x1="5" y1="12" x2="19" y2="12"></line></svg>'
              : '<svg xmlns="http://www.w3.org/2000/svg" width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="diff-icon"><line x1="5" y1="12" x2="19" y2="12"></line></svg>'
          }

          result.push(`
            <div class="diff-line">
              <span class="line-number">${linePrefix}</span>
              ${icon ? `<span class="diff-marker">${icon}</span>` : ''}
              <span class="${className}">${escapeHtml(line)}</span>
            </div>
          `)
        })
        result.push('</div>')
      })
    }
    else {
      changes.forEach((part) => {
        const className = part.added
          ? 'diff-added'
          : part.removed
            ? 'diff-removed'
            : 'diff-equal'

        result.push(`<span class="${className}">${escapeHtml(part.value)}</span>`)
      })
    }
  }

  return result
}

// 切换折叠/展开
export function toggleFold(sectionId: string, foldingConfig: FoldingConfig) {
  const section = document.getElementById(sectionId)
  const button = document.querySelector(`button[data-section-id="${sectionId}"]`) as HTMLElement
  const icon = button?.querySelector('.fold-icon') as SVGElement

  if (section) {
    if (section.style.display === 'none') {
      section.style.display = 'block'
      foldingConfig.expandedSections.add(sectionId)

      if (icon) {
        icon.style.transform = 'rotate(180deg)'
      }

      if (button) {
        const text = button.textContent || ''
        const match = text.match(/(\d+)\s+行相同内容已折叠/)
        if (match && match[1]) {
          button.innerHTML = button.innerHTML.replace(
            /(\d+)\s+行相同内容已折叠/,
            `${match[1]} 行相同内容 (点击折叠)`,
          )
        }
      }
    }
    else {
      section.style.display = 'none'
      foldingConfig.expandedSections.delete(sectionId)

      if (icon) {
        icon.style.transform = 'rotate(0)'
      }

      if (button) {
        const text = button.textContent || ''
        const match = text.match(/(\d+)\s+行相同内容/)
        if (match && match[1]) {
          button.innerHTML = button.innerHTML.replace(
            /(\d+)\s+行相同内容\s+\(点击折叠\)/,
            `${match[1]} 行相同内容已折叠`,
          )
        }
      }
    }
  }
}

// 复制结果
export function copyResult(diffResult: string[]) {
  const { copy } = useClipboard()

  if (diffResult.length === 0) {
    ElMessage.warning('没有可复制的内容')
    return
  }

  const tempDiv = document.createElement('div')
  tempDiv.innerHTML = diffResult.join('')

  let plainText = ''

  const diffLines = tempDiv.querySelectorAll('.diff-line')
  diffLines.forEach((line) => {
    const contentElement = line.querySelector('.diff-added, .diff-removed, .diff-equal')
    if (contentElement) {
      plainText += `${contentElement.textContent}\n`
    }
  })

  const foldedSections = tempDiv.querySelectorAll('.folded-content')
  foldedSections.forEach((section) => {
    if ((section as HTMLElement).style.display !== 'none') {
      const contentLines = section.querySelectorAll('.diff-line')
      contentLines.forEach((line) => {
        const contentElement = line.querySelector('.diff-added, .diff-removed, .diff-equal')
        if (contentElement) {
          plainText += `${contentElement.textContent}\n`
        }
      })
    }
    else {
      plainText += '[... 折叠内容 ...]\n'
    }
  })

  copy(plainText)
  ElMessage.success('已复制到剪贴板')
}
